#!/usr/bin/python3
# ******************************************************************************
# Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
# licensed under the Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#     http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
# PURPOSE.
# See the Mulan PSL v2 for more details.
# ******************************************************************************/
import configparser
import os
import yaml
from exception import ConfigNotFoundError


class DefaultConfig:
    """
    Configuration items that all users may need to modify
    """

    # **********
    # Log related
    # **********
    # level of LOG
    LOGGER_LEVEL = "INFO"
    # Log file path
    LOGGER_PATH = "/var/log/cve_tracking"
    # Log file name
    LOGGER_FILE_NAME = "cve_tracking.log"
    # Log file size, the default is 5 M
    LOGGER_BUFFER = 5242880
    # Number of log files saved
    LOGGER_FILE_COUNT = 20

    # **********
    # Path related
    # **********
    # Patch file download and save path.
    PATCH_SAVE_PATH = "/opt/cve_tracking/patches"
    # Source code package and patch file storage path,
    # used to download gitee source code package and package verification.
    SOURCE_CODE_PATH = "/opt/cve_tracking/source_code"

    # **********
    # Feedback issue related configuration
    # **********

    FEEDBACK_PLATFORM = "github"
    # Feedback to the owner of the issue
    FEEDBACK_ISSUE_OWNER = "liheavy"
    # Feedback to the repo of the issue
    FEEDBACK_ISSUE_REPO = "cve_tracking"

    # The owner of the comment function submits the comment
    DEFAULT_OWNER = "src-openeuler"


class Config:
    """
    Configuration item load and get value
    """

    config_file = os.path.join(
        os.path.dirname(os.path.abspath(os.path.dirname(__file__))), "config.ini"
    )

    def __init__(self):
        self._setattr_default()
        self._setattr_customize()

    def _setattr_default(self):
        """
        Set default configuration items and their values
        :return: self
        """
        for attr in dir(DefaultConfig):
            if not str(attr).startswith("_"):
                setattr(self, attr, getattr(DefaultConfig, attr))

    def _setattr_customize(self):
        """
        Set customize configuration items and their values
        :return: self
        """
        if not os.path.exists(self.config_file):
            raise ConfigNotFoundError(self.config_file)

        conf_parser = configparser.ConfigParser()
        conf_parser.read(self.config_file)
        for section in conf_parser.sections():
            for key_value in conf_parser.items(section):
                if key_value[1]:
                    setattr(self, key_value[0].upper(), key_value[1])

    def __getattr__(self, item):
        """
        When the configuration cannot be found, reload the configuration file
        :param item: config key
        :return: value
        """
        self._setattr_default()
        self._setattr_customize()
        try:
            return self.__dict__[item]
        except KeyError:
            return None


class YamlConfiguration:
    """
    yaml file parsing class
    """
    yaml = os.path.join(
        os.path.dirname(os.path.abspath(os.path.dirname(__file__))), "cve-tracking.yaml"
    )

    def __init__(self) -> None:
        if not os.path.exists(self.yaml):
            raise FileNotFoundError("file not found: %s" % self.yaml)
        self.__dict__.update(self._parse_yaml())

    def _parse_yaml(self):
        with open(self.yaml, "r", encoding="utf-8") as file:
            try:
                configs = yaml.load(file.read(), Loader=yaml.SafeLoader)
            except yaml.YAMLError as error:
                raise ValueError(
                    "The format of the yaml configuration "
                    "file is wrong please check and try again:{0}".format(error)
                )
            else:
                return configs

    def __getattr__(self, name):
        if name not in self.__dict__:
            return None

        return self.__dict__[name]

    def get_platform(self, name=None):
        """
        Get the configured cve platform
        :param name: specify platform name
        :return: platform name
        """
        if name is None:
            return self.platform
        platform = filter(lambda x: x["name"] == name, self.platform)
        if platform:
            return list(platform)[-1]
        return None

    def get_regex(self, label=None):
        """
        Regular expression to get patch
        :param label: issue or pr or commit
        :return: regex
        """
        if label is None:
            regulars = [reg for reg in self.regex]
        else:
            regulars = filter(lambda x: x["label"] == label, self.regex)
        return [regx for reg in regulars for regx in reg["regular"]]

    def token(self, name):
        token = filter(lambda x: x["name"] == name, self.authentication)
        if token:
            return list(token)[-1]["token"]
        return None

    @property
    def configuration(self):
        """
        All configuration items
        :return: dict
        """
        return self.__dict__